import { ErrorCodes, errorMessages, resolveCodeByHttp } from '@boticord/consts'
import { Logger } from '@nestjs/common'
import { ResponseDto } from './response-serializer.dto'

// this is a factory that creates a ResponseDto from a ResponseDtoFactory
// ResponseDto is an interface that is used to serialize the response from the server
// it will send the response as a standardized JSON object
export class ResponseDtoFactory {
  successful<T>(data: T): ResponseDto<T> {
    return {
      ok: true,
      result: data,
      service: process.env.BOTICORD_SERVICE ?? 'unknown',
    }
  }
  
  error(exception: any, logger: Logger): ResponseDto<any> {
    // logger.debug('caught an exception', exception, exception?.stack ?? 'no stack')
    // console.trace(exception)

    const data = exception.getResponse?.() ?? exception.getError?.() ?? exception.message ?? exception
    if (Array.isArray(data?.message ?? '')) {
      const results = data.message.map(e => e.result)
      return {
        ok: false,
        result: results.length ? results : null,
        service: process.env.BOTICORD_SERVICE ?? 'unknown',
        errors: data.message
          .map(e => {
            const code = e?.context?.code
              ?? e?.code
              ?? resolveCodeByHttp(exception?.getStatus?.())
              ?? ErrorCodes.UnknownError
            return {
              code,
              message: 
                (typeof e === 'string' && code !== 0 ? e : undefined) 
                ?? e.message 
                ?? errorMessages[code] 
                ?? errorMessages[ErrorCodes.UnknownError],
            }
          }),
      }
    } else {
      const code = data?.context?.code
        ?? data?.code
        ?? resolveCodeByHttp(exception?.getStatus?.())
        ?? ErrorCodes.UnknownError

      return {
        ok: false,
        result: data?.result ?? null,
        service: process.env.BOTICORD_SERVICE ?? 'unknown',
        errors: data?.errors ?? [
          {
            code,
            message: 
              (typeof data === 'string' && code !== 0 ? data : undefined) 
              ?? data?.message 
              ?? errorMessages[code] 
              ?? errorMessages[ErrorCodes.UnknownError],
          },
        ],
      }
    }
  }
}